package com.ruoyi.boat.codec;

import com.ruoyi.boat.domain.*;
import com.ruoyi.boat.utils.ByteUtil;
import com.ruoyi.boat.utils.DateUtil;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Arrays;

public class MessageDecoder {
    private static final MessageDecoder instance = new MessageDecoder();

    private MessageDecoder() {
    }

    public static MessageDecoder getInstance() {
        return instance;
    }

    //解析0x1003
    public static Status decode1003(byte[] msg) {
        Status result = new Status();
        result.setBoatCode(ByteUtil.byteToHex(msg[6]));
        //需要用long去装载，否则是可能会得到负值
        result.setTime(DateUtil.timestampToDate(
                ByteUtil.bytesToLong(Arrays.copyOfRange(msg, 7, 11))));
        result.setSerialNum(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 11, 13)));
        result.setLng(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 13, 17)) / 1000000.0);
        result.setLat(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 17, 21)) / 1000000.0);
        result.setDestNum(msg[21] & 0xff);
        result.setHeadingDown(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 22, 24)) / 100.0);
        result.setPitchDown((msg[24] & 0xff) <= 90 ? (msg[24] & 0xff) : (msg[24] & 0xff) - 190);
        result.setSpeed((msg[25] & 0xff) / 100.0);
        result.setAlert(msg[26] & 0xff);
        double voltage1 = (msg[27] & 0xff) / 5.0;
        result.setVoltage1(voltage1);
        //取小数点后两位
        String capacitorStr = String.format("%.2f", (voltage1 - 22.4) / 7);
        result.setCapacitor(Double.parseDouble(capacitorStr));
        result.setVoltage2((msg[28] & 0xff) / 5.0);
        result.setVoltage3((msg[29] & 0xff) / 5.0);
        result.setRudderAngle(msg[30] & 0xff);
        result.setControlMode(msg[31] & 0xff);
        result.setSystemStatus(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 32, 34)));
        result.setHeadingUp(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 34, 36)) / 100.0);
        result.setPitchUp((msg[36] & 0xff) <= 90 ? (msg[36] & 0xff) : (msg[36] & 0xff) - 190);
        result.setRollUp((msg[37] & 0xff) <= 90 ? (msg[37] & 0xff) : (msg[37] & 0xff) - 190);
        result.setRotationUp(msg[38] & 0xff);
        result.setRotationDown(msg[39] & 0xff);
        result.setPressure(msg[40] & 0xff);
        result.setActuatorStatus(msg[41] & 0xff);
        result.setLoadStatus(msg[42] & 0xff);
        return result;
    }

    public static MeteorData decode1004(byte[] msg) {
        MeteorData result = new MeteorData();
        result.setBoatCode(ByteUtil.byteToHex(msg[6]));
        result.setTime(DateUtil.timestampToDate(
                ByteUtil.bytesToLong(Arrays.copyOfRange(msg, 7, 11))));
        int temp = ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 13, 15));
        if (temp >= 0x8000) {
            result.setTemp(((0x8000 - temp) / 10.0));
        } else {
            result.setTemp(temp / 10.0);
        }
        result.setHumidity(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 15, 17)) / 10.0);
        result.setWindSpeed(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 17, 19)) / 10.0);
        result.setWindDirection((double) ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 19, 21)));
        result.setPressure(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 23, 25)) / 10.0);
        result.setRain(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 25, 27)) / 10.0);
        return result;
    }

    //一次最多传输4条船的AIS信息
    public static AisData decode1005(byte[] msg) {
        AisData result = new AisData();
        result.setBoatCode(ByteUtil.byteToHex(msg[6]));
        result.setTime(DateUtil.timestampToDate(
                ByteUtil.bytesToLong(Arrays.copyOfRange(msg, 7, 11))));
        result.setLng(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 13, 17)) / 1000000.0);
        result.setLat(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 17, 21)) / 1000000.0);
        int shipNum = msg[21] & 0xff;
        result.setCount(shipNum);
        StringBuilder mmsiSb = new StringBuilder();
        StringBuilder lngSb = new StringBuilder();
        StringBuilder latSb = new StringBuilder();
        StringBuilder speedSb = new StringBuilder();
        StringBuilder directionSb = new StringBuilder();
        for (int i = 0; i < shipNum; i++) {
            //MMSI补0
            mmsiSb.append(String.format("%09d", ByteUtil.bytesToLong(Arrays.copyOfRange(msg, 22 + 16 * i, 26 + 16 * i))));
            mmsiSb.append(",");
            lngSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 26 + 16 * i, 30 + 16 * i)) / 1000000.0);
            lngSb.append(",");
            latSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 30 + 16 * i, 34 + 16 * i)) / 1000000.0);
            latSb.append(",");
            speedSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 34 + 16 * i, 36 + 16 * i)) / 10.0);
            speedSb.append(",");
            directionSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 36 + 16 * i, 38 + 16 * i)));
            directionSb.append(",");
        }
        if (mmsiSb.length() > 0) {
            result.setMmsiList(mmsiSb.substring(0, mmsiSb.length() - 1));
        } else {
            result.setMmsiList("");
        }
        if (lngSb.length() > 0) {
            result.setLngList(lngSb.substring(0, lngSb.length() - 1));
        } else {
            result.setLngList("");
        }
        if (latSb.length() > 0) {
            result.setLatList(latSb.substring(0, latSb.length() - 1));
        } else {
            result.setLatList("");
        }
        if (speedSb.length() > 0) {
            result.setSpeedList(speedSb.substring(0, speedSb.length() - 1));
        } else {
            result.setSpeedList("");
        }
        if (directionSb.length() > 0) {
            result.setDirectionList(directionSb.substring(0, directionSb.length() - 1));
        } else {
            result.setDirectionList("");
        }
        return result;
    }

    public static AtmosData decode1006(byte[] msg) {
        AtmosData result = new AtmosData();
        result.setBoatCode(ByteUtil.byteToHex(msg[6]));
        result.setTime(DateUtil.timestampToDate(
                ByteUtil.bytesToLong(Arrays.copyOfRange(msg, 7, 11))));
        result.setType(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 13, 14)));
        result.setCeilHeight((double) ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 14, 17)));
        result.setBottomHeight((double) ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 17, 20)));
        result.setThickness((double) ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 20, 23)));
        result.setStrength((double) ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 23, 26)));
        Instant instant = result.getTime().toInstant();
        // 使用指定的时区创建java.time.LocalDateTime
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        System.out.println(localDateTime);
        return result;
    }

    public static RadarData decode1007(byte[] msg) {
        RadarData result = new RadarData();
        result.setBoatCode(ByteUtil.byteToHex(msg[6]));
        result.setTime(DateUtil.timestampToDate(
                ByteUtil.bytesToLong(Arrays.copyOfRange(msg, 7, 11))));
        //从 msg[13]开始
        byte[] radarBytes = new byte[msg.length - 13];
        System.arraycopy(msg, 13, radarBytes, 0, radarBytes.length);
        int packageNum = getPackageNum(radarBytes);
        result.setCurrentIndex(packageNum);
        if (packageNum == 9) {
            decodeWindData(result, radarBytes, 2);//两包风数据
            decodeRadarStatus(result, radarBytes);
        } else {
            decodeWindData(result, radarBytes, 4);//四包风数据
        }
        return result;
    }

    //包号 1 为 4包风数据
    //包好 5 为 4包风数据
    //包号 9 为 2包风数据 + 1包状态数据
    public static int getPackageNum(byte[] radarBytes) {
        return radarBytes[7];
    }

    public static void decodeWindData(RadarData radarData, byte[] radarBytes, int packageCount) {
        StringBuilder distanceSb = new StringBuilder();
        StringBuilder hSpeedSb = new StringBuilder();
        StringBuilder hDirectionSb = new StringBuilder();
        StringBuilder ratioSb = new StringBuilder();
        StringBuilder vSpeedSb = new StringBuilder();
        StringBuilder dataRateSb = new StringBuilder();
        StringBuilder sDeviationSb = new StringBuilder();
        StringBuilder maxSpeedSb = new StringBuilder();
        StringBuilder minSpeedSb = new StringBuilder();
        StringBuilder zDeviationSb = new StringBuilder();
        //一层数据是 12 + 200 + 2 个字节 一包里总共有四层
        for (int i = 0; i < packageCount; i++) {
            byte[] tempBytes = new byte[214];
            //得到一层数据
            System.arraycopy(radarBytes, i * 214, tempBytes, 0, 214);
            byte[] tenWindBytes = new byte[200];
            //获得10
            System.arraycopy(tempBytes, 12, tenWindBytes, 0, 200);
            //对这一层进行解析
            for (int j = 0; j < 10; j++) {
                byte[] oneWindBytes = new byte[20];
                System.arraycopy(tenWindBytes, j * 20, oneWindBytes, 0, 20);
                distanceSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(oneWindBytes, 0,  2)));
                distanceSb.append(",");
                hSpeedSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(oneWindBytes,  2,  4)) / 100.0);
                hSpeedSb.append(",");
                hDirectionSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(oneWindBytes,  4, 6)) / 100.0);
                hDirectionSb.append(",");
                ratioSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(oneWindBytes,  6, 8)));
                ratioSb.append(",");
                vSpeedSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(oneWindBytes,  8, 10)) / 100.0);
                vSpeedSb.append(",");
                dataRateSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(oneWindBytes, 10, 12)) / 100.0);
                dataRateSb.append(",");
                sDeviationSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(oneWindBytes, 12, 14)) / 100.0);
                sDeviationSb.append(",");
                maxSpeedSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(oneWindBytes, 14, 16)) / 100.0);
                maxSpeedSb.append(",");
                minSpeedSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(oneWindBytes, 16, 18)) / 100.0);
                minSpeedSb.append(",");
                zDeviationSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(oneWindBytes, 18, 20)) / 100.0);
                zDeviationSb.append(",");
            }
        }
        radarData.setDistanceList(distanceSb.substring(0, distanceSb.length() - 1));
        radarData.setHSpeedList(hSpeedSb.substring(0, hSpeedSb.length() - 1));
        radarData.setHDirectionList(hDirectionSb.substring(0, hDirectionSb.length() - 1));
        radarData.setRatioList(ratioSb.substring(0, ratioSb.length() - 1));
        radarData.setVSpeedList(vSpeedSb.substring(0, vSpeedSb.length() - 1));
        radarData.setDataRateList(dataRateSb.substring(0, dataRateSb.length() - 1));
        radarData.setSDeviationList(sDeviationSb.substring(0, sDeviationSb.length() - 1));
        radarData.setMaxSpeedList(maxSpeedSb.substring(0, maxSpeedSb.length() - 1));
        radarData.setMinSpeedList(minSpeedSb.substring(0, minSpeedSb.length() - 1));
        radarData.setZDeviationList(zDeviationSb.substring(0, zDeviationSb.length() - 1));
    }

    public static void decodeRadarStatus(RadarData radarData, byte[] radarBytes) {
        int startIndex = 214 * 2;//2包风数据
        byte[] statusBytes = new byte[radarBytes.length - startIndex];
        System.arraycopy(radarBytes, startIndex, statusBytes, 0, statusBytes.length);
        radarData.setLng(ByteUtil.bytesToInt(Arrays.copyOfRange(statusBytes, 12, 16)) / 1000000.0);
        radarData.setLat(ByteUtil.bytesToInt(Arrays.copyOfRange(statusBytes, 16, 20)) / 1000000.0);
        radarData.setLaserStatus(statusBytes[20] & 0xff);
        radarData.setAmplifierStatus(statusBytes[21] & 0xff);
        radarData.setLaserPower(ByteUtil.bytesToInt(Arrays.copyOfRange(statusBytes, 22, 24)) / 10.0);
        radarData.setAmplifierPower(ByteUtil.bytesToInt(Arrays.copyOfRange(statusBytes, 24, 26)) / 10.0);
        radarData.setLaserTemp(ByteUtil.bytesToInt(Arrays.copyOfRange(statusBytes, 26, 28)) / 100.0);
        radarData.setAmplifierTemp(ByteUtil.bytesToInt(Arrays.copyOfRange(statusBytes, 28, 30)) / 100.0);
        radarData.setModuleTemp(ByteUtil.bytesToInt(Arrays.copyOfRange(statusBytes, 30, 32)) / 100.0);
        radarData.setModuleHumidity(ByteUtil.bytesToInt(Arrays.copyOfRange(statusBytes, 32, 34)) / 100.0);
        radarData.setInputVoltage(ByteUtil.bytesToInt(Arrays.copyOfRange(statusBytes, 34, 36)) / 100.0);
        radarData.setDiskSpace((statusBytes[36] & 0xff) / 100.0);
        radarData.setMeasurementStatus(statusBytes[37] & 0xff);
    }

    public static WaveData decode1008(byte[] msg) {
        WaveData result = new WaveData();
        result.setBoatCode(ByteUtil.byteToHex(msg[6]));
        result.setTime(DateUtil.timestampToDate(
                ByteUtil.bytesToLong(Arrays.copyOfRange(msg, 7, 11))));
        result.setAverageHeight(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 13, 15)) / 10.0);
        result.setAveragePeriod(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 15, 17)) / 100.0);
        result.setMaxHeight(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 17, 19)) / 10.0);
        result.setMaxPeriod(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 19, 21)) / 100.0);
        result.setOneTenthHeight(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 21, 23)) / 10.0);
        result.setOneTenthPeriod(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 23, 25)) / 100.0);
        result.setSignificantHeight(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 25, 27)) / 10.0);
        result.setSignificantPeriod(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 27, 29)) / 100.0);
        result.setNumber(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 29, 31)));
        result.setDirection(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 31, 33)));
        return result;
    }

    public static AdcpData decode1009(byte[] msg) {
        AdcpData result = new AdcpData();
        result.setBoatCode(ByteUtil.byteToHex(msg[6]));
        result.setTime(DateUtil.timestampToDate(
                ByteUtil.bytesToLong(Arrays.copyOfRange(msg, 7, 11))));
        StringBuilder speedSb = new StringBuilder();
        StringBuilder directionSb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            speedSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 13 + i * 4, 15 + i * 4)) / 100.0);
            speedSb.append(",");
            directionSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 15 + i * 4, 17 + i * 4)));
            directionSb.append(",");
        }
        result.setSpeedList(speedSb.substring(0, speedSb.length() - 1));
        result.setDirectionList(directionSb.substring(0, directionSb.length() - 1));
        return result;
    }

    public static CtdData decode100A(byte[] msg) {
        CtdData result = new CtdData();
        result.setBoatCode(ByteUtil.byteToHex(msg[6]));
        result.setTime(DateUtil.timestampToDate(
                ByteUtil.bytesToLong(Arrays.copyOfRange(msg, 7, 11))));
        StringBuilder tempSb = new StringBuilder();
        StringBuilder salinitySb = new StringBuilder();
        StringBuilder pressureSb = new StringBuilder();
        for (int i = 0; i < (msg[13] & 0xff); i++) {
            tempSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 14 + 6 * i, 16 + 6 * i)) / 100.0);
            tempSb.append(",");
            salinitySb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 16 + 6 * i, 18 + 6 * i)) / 100.0);
            salinitySb.append(",");
            pressureSb.append(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 18 + 6 * i, 20 + 6 * i)) / 100.0);
            pressureSb.append(",");
        }
        if (tempSb.length() > 0) {
            result.setTempList(tempSb.substring(0, tempSb.length() - 1));
        } else {
            result.setTempList("");
        }
        if (salinitySb.length() > 0) {
            result.setSalinityList(salinitySb.substring(0, salinitySb.length() - 1));
        } else {
            result.setSalinityList("");
        }
        if (pressureSb.length() > 0) {
            result.setPressureList(pressureSb.substring(0, pressureSb.length() - 1));
        } else {
            result.setPressureList("");
        }
        return result;
    }

    public static WaterQuality decode100B(byte[] msg) {
        WaterQuality result = new WaterQuality();
        result.setBoatCode(ByteUtil.byteToHex(msg[6]));
        result.setTime(DateUtil.timestampToDate(
                ByteUtil.bytesToLong(Arrays.copyOfRange(msg, 7, 11))));
        result.setTemp(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 13, 15)) / 100.0);
        result.setDepth(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 15, 17)) / 100.0);
        result.setSalinity(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 17, 19)) / 100.0);
        result.setOxygen(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 19, 21)) / 100.0);
        result.setChlorophyll(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 21, 23)) / 100.0);
        result.setTurbidity(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 23, 25)) / 100.0);
        result.setPh(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 25, 27)) / 100.0);
        return result;
    }

    public static CmdResponse decode6912(byte[] msg) {
        CmdResponse result = new CmdResponse();
        result.setBoatCode(ByteUtil.byteToHex(msg[6]));
        result.setResponseTime(DateUtil.timestampToDate(
                ByteUtil.bytesToLong(Arrays.copyOfRange(msg, 7, 11))));
        result.setSerialNum(ByteUtil.bytesToInt(Arrays.copyOfRange(msg, 11, 13)));
        result.setResult(msg[13] & 0xff);
        return result;
    }
}
